package com.geekgo.distributedlock.redissonlock;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.io.InputStream;

/**
 * 创建分布式锁模板实例的工厂Bean
 * @author geekgo
 * @version 2017/2/9 17:41
 */

public class DistributedLockFactoryBean implements FactoryBean<DistributedLockTemplate>{

    private Logger LOG = LogManager.getLogger(DistributedLockFactoryBean.class);
    private LockInstanceMode mode;
    private DistributedLockTemplate distributedLockTemplate;
    private RedissonClient redissonClient;


    @PostConstruct
    public void init(){

        LOG.debug("初始化分布式锁模板");
        InputStream inputStream = null;
        Config config = null;
        try {
            inputStream = DistributedLockFactoryBean.class.getClassLoader().getResourceAsStream("redisson-single.yml");
            config = Config.fromYAML(inputStream);
        } catch (IOException e) {
            LOG.error("读取redisson配置失败",e);
        } finally {
            if(inputStream!=null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    LOG.error("流关闭失败", e);
                }
            }
        }
        Assert.notNull(config);
        redissonClient = Redisson.create(config);
    }

    @PreDestroy
    public void destroy(){
        LOG.debug("销毁分布式锁模板");
        redissonClient.shutdown();
    }

    @Override
    public DistributedLockTemplate getObject() throws Exception {
        switch (mode){
            case SINGLE:
                distributedLockTemplate = new SingleDistributedLockTemplate(redissonClient);
                break;
        }
        return distributedLockTemplate;
    }

    @Override
    public Class<?> getObjectType() {
        return DistributedLockTemplate.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    public void setMode(String mode){
        if(StringUtils.isEmpty(mode)){
            throw new IllegalArgumentException("未找到redisson.mode配置项");
        }
        this.mode = LockInstanceMode.parse(mode);
        if(this.mode == null){
            throw new IllegalArgumentException("不支持的分布式锁模式");
        }
    }

    private enum LockInstanceMode{
        SINGLE;
        public static LockInstanceMode parse(String name){
            for(LockInstanceMode modeIns:LockInstanceMode.values()){
                if(modeIns.name().equals(name.toUpperCase())){
                    return modeIns;
                }
            }
            return null;
        }
    }
}
